use derive_builder::Builder;
use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use crate::{
    error::Error,
    modeling::{PagingResponse, Value},
};

use crate::database::DataSource;

use super::{AttributeCondition, ClassRelationCondition, QueryCondition};

#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "QueryOptionsBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct QueryOptions {
    pub primary_key: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "UpdateConditionBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct UpdateCondition {
    pub attributes: Option<Vec<AttributeCondition>>,
    pub relations: Option<Vec<ClassRelationCondition>>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "DeleteConditionBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct DeleteCondition {
    pub attributes: Option<Vec<AttributeCondition>>,
    pub relations: Option<Vec<ClassRelationCondition>>,
}

/// 满足条件的附加信息
#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "QueryExtentionBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct QueryExtention {
    pub class_selector: HashMap<String, (String, QueryCondition, Option<QueryExtention>)>,
    pub limit: Option<u32>,
    pub is_single: Option<bool>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct UpdateOptions {
    pub upsert: Option<bool>,
    pub primary_key: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct DeleteOptions {
    pub primary_key: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "InsertOptionsBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct InsertOptions {
    pub upsert: Option<bool>,
    pub primary_key: Option<String>,
    pub ignores: Option<Vec<String>>,
}

#[async_trait::async_trait]
pub trait DataSourceConnector {
    async fn datasource(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: u32,
    ) -> anyhow::Result<DataSource>;

    /// 从数据源中通过获取某个类型数据
    async fn instance_query_one_by_keys(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        keys: Vec<String>,
    ) -> anyhow::Result<Value>;

    /// 查询单个值
    async fn instance_query_one(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        conditions: QueryCondition,
        extentions: Option<QueryExtention>,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<Value>;

    /// 查询
    async fn instance_query(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        conditions: QueryCondition,
        extentions: Option<QueryExtention>,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<PagingResponse<Vec<Value>>>;

    /// 查询
    async fn instance_count(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        conditions: QueryCondition,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<u32>;

    /// 获取SQL和参数
    async fn instance_query_sql(
        &self,
        meta_datasource: &Option<DataSource>,
        class_identifier: &String,
        conditions: QueryCondition,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<(String, String, Vec<Value>)>;

    /// 从数据源中通过获取某个类型数据
    async fn instance_update_by_keys(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        keys: Vec<String>,
        value: HashMap<String, Value>,
        options: Option<UpdateOptions>,
    ) -> anyhow::Result<Value>;

    /// 从数据源中通过获取某个类型数据
    async fn instance_update(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        condition: UpdateCondition,
        value: HashMap<String, Value>,
        options: Option<UpdateOptions>,
    ) -> anyhow::Result<Value>;

    /// 从数据源中通过获取某个类型数据
    async fn instance_delete_by_keys(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        keys: Vec<String>,
        options: Option<DeleteOptions>,
    ) -> anyhow::Result<Value>;

    /// 从数据源中通过获取某个类型数据
    async fn instance_delete(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        conditions: DeleteCondition,
        options: Option<DeleteOptions>,
    ) -> anyhow::Result<Value>;

    /// 插入
    async fn instance_insert(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        class_identifier: &String,
        values: HashMap<String, Value>,
        options: Option<InsertOptions>,
    ) -> anyhow::Result<Value>;

    /// 查询
    async fn batch_instance_query(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        querys: Vec<(String, QueryCondition, Option<QueryExtention>)>,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<Vec<PagingResponse<Vec<Value>>>> {
        let mut result: Vec<PagingResponse<Vec<Value>>> = vec![];
        for (s, c, e) in querys {
            result.push(
                self.instance_query(meta_datasource, datasource, &s, c, e, options.clone())
                    .await?,
            );
        }
        Ok(result)
    }

    /// 获取SQL和参数
    async fn batch_instance_query_sql(
        &self,
        meta_datasource: &Option<DataSource>,
        querys: Vec<(String, QueryCondition)>,
        options: Option<QueryOptions>,
    ) -> anyhow::Result<Vec<(String, String, Vec<Value>)>> {
        let mut result: Vec<(String, String, Vec<Value>)> = vec![];
        for (s, c) in querys {
            result.push(
                self.instance_query_sql(meta_datasource, &s, c, options.clone())
                    .await?,
            );
        }
        Ok(result)
    }

    /// 批量插入
    async fn batch_instance_insert(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        inserts: Vec<(String, HashMap<String, Value>)>,
        options: Option<InsertOptions>,
    ) -> anyhow::Result<Vec<Value>> {
        let mut result: Vec<Value> = vec![];
        for (s, c) in inserts {
            result.push(
                self.instance_insert(meta_datasource, datasource, &s, c, options.clone())
                    .await?,
            );
        }
        Ok(result)
    }

    /// 批量更新
    async fn batch_instance_update(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        items: Vec<(String, UpdateCondition, HashMap<String, Value>)>,
        options: Option<UpdateOptions>,
    ) -> anyhow::Result<Vec<Value>> {
        let mut result: Vec<Value> = vec![];
        for (s, c, v) in items {
            result.push(
                self.instance_update(meta_datasource, datasource, &s, c, v, options.clone())
                    .await?,
            );
        }
        Ok(result)
    }

    /// 批量删除
    async fn batch_instance_delete(
        &self,
        meta_datasource: &Option<DataSource>,
        datasource: &DataSource,
        items: Vec<(String, DeleteCondition)>,
        options: Option<DeleteOptions>,
    ) -> anyhow::Result<Vec<Value>> {
        let mut result: Vec<Value> = vec![];
        for (s, c) in items {
            result.push(
                self.instance_delete(meta_datasource, datasource, &s, c, options.clone())
                    .await?,
            );
        }
        Ok(result)
    }
}
